package com.zrm.zfcrpa.configuration.security.mobile;

import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.zrm.zfcrpa.configuration.security.MyUserDetals;
import com.zrm.zfcrpa.dao.mapper.loginMapper.LoginDao;
import com.zrm.zfcrpa.utils.MyJwtUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.InternalAuthenticationServiceException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class SmsCodeAuthenticationFilter extends AbstractAuthenticationProcessingFilter {

    private static final String LOGIN_URL = "/authMobile/login";

    private static final String EXPIRETION_URL = "/MyExpiretionHandler";

    private static final String METHOD = "POST";

    //无法自动注入，只能从外部注入
    private RedisTemplate redisTemplate;

    private LoginDao loginDao;

    private MyUserDetals myUserDetals;

    public SmsCodeAuthenticationFilter(RedisTemplate redisTemplate, LoginDao loginDao, MyUserDetals myUserDetals) {
        this();
        this.redisTemplate = redisTemplate;
        this.loginDao = loginDao;
        this.myUserDetals = myUserDetals;
    }


    protected SmsCodeAuthenticationFilter() {
        super(new AntPathRequestMatcher(LOGIN_URL, METHOD));
    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException, InternalAuthenticationServiceException {
        HttpServletRequest request = ((ServletRequestAttributes) (RequestContextHolder.currentRequestAttributes())).getRequest();
        String url = request.getRequestURI();
        if (url.contains(LOGIN_URL) && request.getMethod().equals(METHOD)) {
            String phone = req.getParameter("phone");
            String code = req.getParameter("code");
            String loginType = req.getParameter("loginType");
            String rcode = (String) redisTemplate.opsForValue().get(phone);
            if (!code.equals("") && code != null && rcode != null && rcode.equals(code)) {
                myUserDetals.login_info(phone, loginType);
                super.doFilter(req, res, chain);
            } else {
                String errorMsg = code.equals("") || code == null ? "验证码不能为空" : rcode == null ? "验证码已过期" : "验证码错误";
                req.setAttribute("e", errorMsg);
                req.setAttribute("msg", "手机验证异常");
                req.getRequestDispatcher(EXPIRETION_URL).forward(req, res);
            }
        } else {
            super.doFilter(req, res, chain);
        }
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws AuthenticationException, IOException, ServletException {
        String mobile = httpServletRequest.getParameter("phone");
        if (mobile == null) {
            mobile = "";
        }
        SmsCodeAuthToken authToken = new SmsCodeAuthToken(mobile);
        this.setDetails(httpServletRequest, authToken);
        return this.getAuthenticationManager().authenticate(authToken);
    }

    protected void setDetails(HttpServletRequest request, SmsCodeAuthToken smsCodeAuthToken) {
        smsCodeAuthToken.setDetails(this.authenticationDetailsSource.buildDetails(request));
    }

    @Override
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException {
        User user = (User) authResult.getPrincipal();
        Map<String, Object> map = new HashMap<>();
        JSONObject object = loginDao.getUserInfo(user.getUsername());
        List<String> collation = user.getAuthorities().stream().map(m -> {
            return m.getAuthority();
        }).collect(Collectors.toList());
        String token = MyJwtUtils.createToken(user.getUsername(), collation.get(0), object);
        map.put("token", token);
        map.put("userObject", object);
        System.out.println("23");
        response.setHeader("Content-Type", "text/html;charset=UTF-8");
        response.getWriter().write(new ObjectMapper().writeValueAsString(map));
    }
}
